package com.yunwushanhe.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.BeanUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunwushanhe.bean.req.MenuSelectReq;
import com.yunwushanhe.bean.req.MenuUpdateReq;
import com.yunwushanhe.bean.ret.ResponseResult;
import com.yunwushanhe.bean.vo.*;
import com.yunwushanhe.constant.Constant;
import com.yunwushanhe.enums.AppHttpCodeEnum;
import com.yunwushanhe.mapper.MenuMapper;
import com.yunwushanhe.entity.Menu;
import com.yunwushanhe.service.MenuService;
import com.yunwushanhe.util.BeanCopyUtil;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.management.remote.JMXServiceURL;
import javax.security.auth.callback.LanguageCallback;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单权限表(Menu)表服务实现类
 *
 * @author 抬头看看天
 * @since 2023-08-17 15:56:13
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Resource
    private MenuMapper menuMapper;

    @Override
    public List<String> selectPermListByUserId(Long userId) {
        // 如果是超级管理员，则返回所有权限
        if(userId == 1L){
            LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Menu::getMenuType, Constant.MENU_TYPE_C,Constant.MENU_TYPE_F);
            wrapper.eq(Menu::getStatus,Constant.MENU_STATUS_NORMAL);
            List<Menu> menuList = list(wrapper);
            List<String> permList = menuList.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
            return permList;
        }
        return menuMapper.selectPermListByUserId(userId);
    }

    @Override
    public ResponseResult<RouterListVO> selectRouterMenuTreeByUserId(Long userId) {
        List<Menu> menuList = null;
        if(userId == 1L){
            menuList = menuMapper.selectAllRouterMenu();
        } else {
            menuList = menuMapper.selectRouterMenuTreeByUserId(userId);
        }
        List<MenuVO> menuVOList = BeanCopyUtil.copyBeanList(menuList, MenuVO.class);
        //构建tree
        List<MenuVO> menuVOListTree = builderMenuTree(menuVOList,0L);

        return ResponseResult.ok(new RouterListVO(menuVOListTree));
    }

    @Override
    public ResponseResult<List<MenuSelectAllVO>> listAllMenu(MenuSelectReq menuSelectReq) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.hasText(menuSelectReq.getStatus()),Menu::getStatus,menuSelectReq.getStatus());
        queryWrapper.like(StringUtils.hasText(menuSelectReq.getMenuName()),Menu::getMenuName,menuSelectReq.getMenuName());
        queryWrapper.orderByAsc(Menu::getOrderNum).orderByAsc(Menu::getParentId);

        List<Menu> menuList = list(queryWrapper);

        List<MenuSelectAllVO> menuSelectAllVOList = BeanCopyUtil.copyBeanList(menuList, MenuSelectAllVO.class);

        return ResponseResult.ok(menuSelectAllVOList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<Object> addMenu(Menu menu) {
        save(menu);
        return ResponseResult.ok();
    }

    @Override
    public ResponseResult<MenuUpdateVO> selectMenuById(Long id) {
        Menu menu = getById(id);
        MenuUpdateVO menuUpdateVO = BeanCopyUtil.copyBean(menu, MenuUpdateVO.class);
        return ResponseResult.ok(menuUpdateVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<Object> updateMenuById(MenuUpdateReq menuUpdateReq) {

        // 检测本身不能成为自己的父菜单
        if(menuUpdateReq.getId().equals(menuUpdateReq.getParentId())){
            return ResponseResult.error(AppHttpCodeEnum.MENU_CHOOSE_ERROR);
        }

        HashMap<String, Object> eqMap = new HashMap<>();
        eqMap.put("id",menuUpdateReq.getId());
        UpdateWrapper<Menu> menuUpdateWrapper =
                BeanCopyUtil.ignoreNullUpdateWrapper(eqMap, menuUpdateReq, Menu.class);

        update(menuUpdateWrapper);
        return ResponseResult.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<Object> deleteMenuById(Long id) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getParentId,id);
        List<Menu> menuList = list(queryWrapper);

        if(menuList.size() != 0){
            return ResponseResult.error(AppHttpCodeEnum.MENU_REMOVE_ERROR);
        }

        removeById(id);
        return ResponseResult.ok();
    }

    @Override
    public ResponseResult<List<MenuTreeVO>> getMenuTree() {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getStatus,Constant.MENU_STATUS_NORMAL);
        queryWrapper.orderByAsc(Menu::getOrderNum);
        List<Menu> menuList = list(queryWrapper);

        List<MenuTreeVO> menuTreeVOS = BeanCopyUtil.copyBeanList(menuList, MenuTreeVO.class);
        for (int i = 0; i < menuTreeVOS.size(); i++) {
            menuTreeVOS.get(i).setLabel(menuList.get(i).getMenuName());
        }
        List<MenuTreeVO> menuTreeVOList = builderMenuTreeVO(menuTreeVOS, 0L);

        return ResponseResult.ok(menuTreeVOList);
    }

    private List<MenuTreeVO> builderMenuTreeVO(List<MenuTreeVO> menuTreeVOList, Long parentId) {
        List<MenuTreeVO> menuTree = menuTreeVOList.stream()
                .filter(menuTreeVO -> menuTreeVO.getParentId().equals(parentId))
                .map(menuTreeVO -> menuTreeVO.setChildren(getChildrenVO(menuTreeVO, menuTreeVOList)))
                .collect(Collectors.toList());
        return menuTree;
    }

    private List<MenuTreeVO> getChildrenVO(MenuTreeVO menuTreeVO, List<MenuTreeVO> menuTreeVOList) {
        List<MenuTreeVO> childrenList = menuTreeVOList.stream()
                .filter(m -> m.getParentId().equals(menuTreeVO.getId()))
                .map(m->m.setChildren(getChildrenVO(m,menuTreeVOList)))
                .collect(Collectors.toList());
        return childrenList;
    }


    private List<MenuVO> builderMenuTree(List<MenuVO> menuVOList, Long parentId) {
        List<MenuVO> menuTree = menuVOList.stream()
                .filter(menuVO -> menuVO.getParentId().equals(parentId))
                .map(menuVO -> menuVO.setChildren(getChildren(menuVO, menuVOList)))
                .collect(Collectors.toList());
        return menuTree;
    }

    /**
     * 获取存入参数的 子Menu集合
     * @param menuVO
     * @param menuVOList
     * @return
     */
    private List<MenuVO> getChildren(MenuVO menuVO, List<MenuVO> menuVOList) {
        List<MenuVO> childrenList = menuVOList.stream()
                .filter(m -> m.getParentId().equals(menuVO.getId()))
                .map(m->m.setChildren(getChildren(m,menuVOList)))
                .collect(Collectors.toList());
        return childrenList;
    }
}

